package com.xunqi.content.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xunqi.common.dto.content.ShareAuditDTO;
import com.xunqi.common.dto.content.ShareDTO;
import com.xunqi.common.dto.user.UserAddBonseDTO;
import com.xunqi.common.dto.user.UserAddBonusMsgDTO;
import com.xunqi.common.dto.user.UserDTO;
import com.xunqi.common.entity.content.MidUserShare;
import com.xunqi.common.entity.content.RocketmqTransactionLog;
import com.xunqi.common.entity.content.Share;
import com.xunqi.common.enums.AuditStatusEnum;
import com.xunqi.content.dao.MidUserShareDao;
import com.xunqi.content.dao.RocketmqTransactionLogDao;
import com.xunqi.content.dao.ShareDao;
import com.xunqi.content.feignclient.UserCenterFeignClient;
import com.xunqi.content.service.ShareService;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.springframework.beans.BeanUtils;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Created with IntelliJ IDEA.
 * @author: 夏沫止水
 * @create: 2020-04-17 10:42
 **/
@Service("shareService")
public class ShareServiceImpl implements ShareService {

    @Resource
    private ShareDao shareDao;

    @Resource
    private MidUserShareDao midUserShareDao;

    @Resource
    private UserCenterFeignClient userCenterFeignClient;

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    @Resource
    private RocketmqTransactionLogDao rocketmqTransactionLogDao;

    @Resource
    private Source source;

    @Override
    public ShareDTO findById(Integer id) {

        //获取分享详情
        Share share = shareDao.queryById(id);

        //发布人id
        Integer userId = share.getUserId();

        //查询用户微服务用户信息
        UserDTO userDTO = userCenterFeignClient.findById(userId);

        //消息的装配
        ShareDTO shareDTO = new ShareDTO();
        BeanUtils.copyProperties(share,shareDTO);
        shareDTO.setWxNickName(userDTO.getWxNickname());

        return shareDTO;
    }

    @Override
    public Share auditById(Integer id, ShareAuditDTO auditDTO) {

        //1.查询share是否存在，不存在或者当前的audit_status != NOT_YET,那么抛出异常
        Share share = shareDao.queryById(id);

        if (share == null) {
            throw new IllegalArgumentException("参数非法！该分享不存在！");
        }

        if (!Objects.equals("NOT_YET",share.getAuditStatus())) {
            throw new IllegalArgumentException("参数非法！该分享已审核通过或者审核不通过！");
        }

        //如果是PASS，那么发消息个rocketmq，让用户中心去消费，并为发布人添加积分
        //异步执行
        if (AuditStatusEnum.PASS.equals(auditDTO.getAuditStatusEnum())) {
            //发送半消息
            String transactionId = UUID.randomUUID().toString();

            Message<UserAddBonusMsgDTO> build = MessageBuilder.withPayload(
                    UserAddBonusMsgDTO.builder()
                            .userId(share.getUserId())
                            .bonus(50)
                            .build()
            )
                    .setHeader(RocketMQHeaders.TRANSACTION_ID, transactionId)
                    .setHeader("share_id", id)
                    .setHeader("dto", JSON.toJSONString(auditDTO))
                    .build();

            //发送消息给用户微服务
            this.source.output().send(build);

        } else {
            this.auditByIdInDB(id,auditDTO);
        }

        return share;
    }

    /**
     * 做数数据库的审核
     * @param id
     * @param auditDTO
     */
    @Transactional(rollbackFor = Exception.class)
    public void auditByIdInDB(Integer id, ShareAuditDTO auditDTO) {

        Share share = Share.builder()
                .id(id)
                .auditStatus(auditDTO.getAuditStatusEnum().toString())
                .reason(auditDTO.getReason())
                .build();

        //2.审核资源，将状态设为PASS/REJECT
        shareDao.update(share);

    }

    @Override
    public void auditByIdWithRocketMqLog(Integer id, ShareAuditDTO auditDTO, String transactionId) {

        this.auditByIdInDB(id,auditDTO);

        //审核成功之后添加一条日志
        RocketmqTransactionLog log = RocketmqTransactionLog.builder()
                .transactionId(transactionId)
                .log("审核分享...")
                .build();

        this.rocketmqTransactionLogDao.insert(log);

    }

    @Override
    public PageInfo<Share> q(String title, Integer pageNo, Integer pageSize, Integer userId) {

        //表示分页，它会切入下面这条不分页的SQL，自动拼接分页的SQL
        PageHelper.startPage(pageNo,pageSize);

        //不分页的SQL,可根据标题查询数据
        List<Share> shares = shareDao.queryAll(Share.builder().title(title).build());

        List<Share> shareDeal;

        //根据前台传过来的用户id是否存在，如果用户未登录，那么downloadUrl全部设置为空
        if (userId == null) {
            shareDeal = shares.stream()
                    .peek(share -> {
                        share.setDownloadUrl(null);
                    }).collect(Collectors.toList());
        } else {
            //如果用户是已登录状态，那么查询了一下mid_user_share，如果没有数据，那么这条share的downloadUrl全部设为空


            shareDeal = shares.stream().
                    peek(share -> {
                        MidUserShare midUserShare = midUserShareDao.queryAll(
                                MidUserShare.builder()
                                        .userId(userId)
                                        .shareId(share.getId())
                                        .build()
                        ).get(0);

                        if (midUserShare == null) {
                            share.setDownloadUrl(null);
                        }

                    }).collect(Collectors.toList());
        }

        return new PageInfo<>(shareDeal);
    }

    @Override
    public Share exchangeById(Integer id, HttpServletRequest request) {

        //1.根据id查询share，效验是否存在
        Share share = this.shareDao.queryById(id);

        if (share == null) {
            throw new IllegalArgumentException("该分享不存在!");
        }

        Integer userId = (Integer) request.getAttribute("id");
        Integer price = share.getPrice();

        //2.如果当前用户已经兑换过该分享就直接返回，不扣减积分
        MidUserShare midUserShare = midUserShareDao.queryAll(
                MidUserShare.builder()
                        .userId(userId)
                        .shareId(id)
                        .build()
        ).get(0);

        if (midUserShare != null) {
            return share;
        }

        //3.根据当前登录用户的id，查询积分是否足够
        UserDTO userDTO = this.userCenterFeignClient.findById(userId);

        if (userDTO.getBonus() < share.getPrice()) {
            throw new IllegalArgumentException("用户的积分不足！");
        }

        this.userCenterFeignClient.addBonus(
                UserAddBonseDTO.builder()
                        .userId(userId)
                        .bonus(0-price)
                        .build()
        );

        //4.扣减积分 & 往mid_user_share里插入一条数据
        this.midUserShareDao.insert(
                MidUserShare.builder()
                        .userId(userId)
                        .shareId(id)
                        .build()
        );

        return share;
    }
}
